<template>
  <div class="kw-tree">
    <ul>
      <li v-for="(item, index) in data" :key="index">
        <div class="kw-tree-node" :class="item[activeField]? 'active': ''" @click="handlerStatusChange(item)">
          <i v-if="item.children && item.children.length > 0" class="iconfont" :class="item.expand? 'icon-arrow-down': 'icon-arrow-right'"></i>
          <kw-checkbox v-if="multiple" v-model="item[selectField]" style="margin: 0 5px;"
                       @on-click="(e)=> {handlerCheckboxClick(e, item)}"
                       @on-change="(status)=> {handlerCheckStatusChange(status, item)}">
          </kw-checkbox>
          <span @click="handlerItemClick(item)">{{item[label]}}</span>
        </div>
        <kw-tree v-if="item.children && item.children.length > 0" v-show="item.expand" :data="item.children"></kw-tree>
      </li>
    </ul>
  </div>
</template>

<script>
  export default {
    name: 'kw-tree',
    props: {
      data: Array,
      label: {
        type: String,
        default: 'name'
      },
      multiple: {
        type: Boolean,
        default: false
      },
      selectField: {
        type: String,
        default: 'selected'
      },
      activeField: {
        type: String,
        default: 'active'
      },
      expandField: {
        type: String,
        default: 'expand'
      }
    },
    data() {
      return {
        checkedList: []
      }
    },
    created() {
      this.$on('item-click', this.handleChildItemClick)
      this.$on('child-check-status-change', this.handlerChildCheckStatusChange)
    },
    methods: {
      handleChildItemClick() {
        this.toggleClearActive(this.data)
      },
      handlerChildCheckStatusChange(item) {
        let flag = false
        this.data.every(o => {
          let checkedCount = 0, indemCount = 0
          o.children.map(c => {
            if (c[this.selectField] === true ||
              c[this.selectField] === 'selected') {
              checkedCount++
            } else if (c[this.selectField] === 'indeterminate') {
              indemCount++
            }
            if (c === item) {
              flag = true
            }
            if (flag) {
              this.$set(o, 'selected', o.children.length === checkedCount? 'selected': (checkedCount > 0 || indemCount > 0? 'indeterminate': 'none'))
              this.$parent.$emit('child-check-status-change', o)
            }
          })
          return !flag
        })
      },
      handlerStatusChange(item) {
        this.$set(item, 'expand', !item.expand)
      },
      handlerItemClick(item) {
        // leaf
        if (!item.children) {
          if (!this.multiple) {
            if (!item.active) {
              this.$parent.$emit('item-click', item)
            }
            this.$set(item, this.activeField, !item[this.activeField])
          }
        }
      },
      handlerCheckboxClick(e) {
        e.stopPropagation()
        e.preventDefault()
      },
      handlerCheckStatusChange(status, item) {
        this.$set(item, 'selected', !item[this.selectField])
        this.toggleCheckStatus(item.children, status)
        this.$parent.$emit('child-check-status-change', item)
      },
      getSelectedData() {
        this.checkedList = []
        if (this.multiple) {
          this.toggleChecked(this.data)
        } else {
          this.toggleActived(this.data)
        }
        return this.checkedList
      },
      toggleClearActive(list) {
        if (list) {
          if (this.name === this.$parent.$options.name) {
            this.$parent.$emit('item-click')
          } else {
            list.forEach(o => {
              this.$set(o, 'active', false)
              this.toggleClearActive(o.children)
            })
          }
        }
      },
      toggleCheckStatus(list, status) {
        if (list) {
          list.forEach(o => {
            this.$set(o, 'selected', status)
            this.toggleCheckStatus(o.children, status)
          })
        }
      },
      toggleChecked(list) {
        if (list) {
          list.map(o => {
            let obj = o[this.selectField]
            if (obj === true || obj === 'selected' || obj === 'indeterminate') {
              if (o.children && o.children.length > 0) {
                this.toggleChecked(o.children)
              } else {
                this.checkedList.push(o)
              }
            }
          })
        }
      },
      toggleActived(list) {
        if(list) {
          list.map(o => {
            let obj = o[this.activeField]
            if (obj) {
              this.checkedList.push(o)
            }
            this.toggleActived(o.children)
          })
        }
      }
    }
  }
</script>

<style lang="less">
  .kw-tree {
    ul {
      padding-left: 20px;
      margin: 0;
    }
    .kw-tree-node {
      padding: 5px;
      margin: 5px 0;
      cursor: pointer;
      background-color: white;
      position: relative;
      &.active {
        background-color: rgba(0,0,0,0.2)
      }
    }
  }
</style>